package com.heu.blood.storge.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.heu.blood.common.utils.PageUtils;
import com.heu.blood.common.utils.Query;
import com.heu.blood.globalExceptionHandler.MyException;
import com.heu.blood.match.dao.BloodInformationDao;
import com.heu.blood.match.entity.BloodInformationEntity;
import com.heu.blood.match.service.BloodInformationService;
import com.heu.blood.security.dao.UserDao;
import com.heu.blood.security.entity.UserEntity;
import com.heu.blood.security.exception.UserLoginException;
import com.heu.blood.storge.dao.BloodOutStorgeDao;
import com.heu.blood.storge.dto.BloodOutStorageDTO;
import com.heu.blood.storge.entity.BloodOutStorgeEntity;
import com.heu.blood.storge.exception.BloodOutStorageException;
import com.heu.blood.storge.exception.InstorageException;
import com.heu.blood.storge.service.BloodInStorgeService;
import com.heu.blood.storge.service.BloodOutStorgeService;
import com.heu.blood.storge.vo.BloodOutStorgeEntityVo;
import com.heu.blood.storge.vo.BloodUrgentOutStorageVo;
import lombok.extern.slf4j.Slf4j;
import org.apache.logging.log4j.util.Strings;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;

import static com.heu.blood.common.enums.CommonEnum.IF_SHOW;
import static com.heu.blood.common.enums.CommonEnum.IS_NOT_DELETED;
import com.heu.blood.storge.entity.BloodInStorgeEntity;
import com.heu.blood.charge.entity.BloodChargeEntity;
import com.heu.blood.charge.service.BloodChargeService;
import com.heu.blood.charge.dictenum.BloodChargeTypeEnum;
import com.heu.blood.charge.dictenum.PaymentProjectEnum;
import com.heu.blood.common.enums.BloodChargeEnum;
import com.heu.blood.application.entity.BloodApplicationItemEntity;
import com.heu.blood.application.service.BloodApplicationItemService;
import com.heu.blood.common.utils.GenerateNumberBySnowFlake;
import com.heu.blood.storge.dictenum.OutStorageReasonEnum;
import com.heu.blood.common.enums.BloodStateEnum;
import com.heu.blood.common.Constant.ConstantData;

@Slf4j
@Service("bloodOutStorgeService")
public class BloodOutStorgeServiceImpl extends ServiceImpl<BloodOutStorgeDao, BloodOutStorgeEntity> implements BloodOutStorgeService {
    @Autowired
    BloodOutStorgeDao bloodOutStorgeDao;

    @Autowired
    BloodInformationService bloodInformationService;

    @Autowired
    BloodInStorgeService bloodInStorgeService;

    @Autowired
    BloodInformationDao bloodInformationDao;

    @Autowired
    private BloodChargeService bloodChargeService;
    @Autowired
    private BloodOutStorgeService bloodOutStorgeService;

    @Autowired
    private BloodApplicationItemService bloodApplicationItemService;

    @Autowired
    private UserDao userDao;

    @Override
    public PageUtils queryPage(BloodOutStorageDTO bloodOutStorageDTO) {
        // 构造查询条件
        LambdaQueryWrapper<BloodOutStorgeEntity> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper
                .like(Strings.isNotBlank(bloodOutStorageDTO.getBloodId()), BloodOutStorgeEntity::getBloodId, bloodOutStorageDTO.getBloodId())
                .like(Strings.isNotBlank(bloodOutStorageDTO.getOperatorName()), BloodOutStorgeEntity::getOperatorName, bloodOutStorageDTO.getOperatorName())
                .eq(Strings.isNotBlank(bloodOutStorageDTO.getAboBloodType()), BloodOutStorgeEntity::getAboBloodType, bloodOutStorageDTO.getAboBloodType())
                .eq(Strings.isNotBlank(bloodOutStorageDTO.getRhBloodType()), BloodOutStorgeEntity::getRhBloodType, bloodOutStorageDTO.getRhBloodType())
                .eq(Strings.isNotBlank(bloodOutStorageDTO.getBloodType()), BloodOutStorgeEntity::getBloodType, bloodOutStorageDTO.getBloodType())
                .eq(Strings.isNotBlank(bloodOutStorageDTO.getOutStorgeReason()), BloodOutStorgeEntity::getOutStorgeReason, bloodOutStorageDTO.getOutStorgeReason())
                .eq(Strings.isNotBlank(bloodOutStorageDTO.getOperatorId()), BloodOutStorgeEntity::getOperatorId, bloodOutStorageDTO.getOperatorId())
                .eq(Strings.isNotBlank(bloodOutStorageDTO.getOutStorgeReason()), BloodOutStorgeEntity::getOutStorgeReason, bloodOutStorageDTO.getOutStorgeReason())
                .ge(Strings.isNotBlank(bloodOutStorageDTO.getStartTime()), BloodOutStorgeEntity::getGmtCreate, bloodOutStorageDTO.getStartTime())
                .le(Strings.isNotBlank(bloodOutStorageDTO.getEndTime()), BloodOutStorgeEntity::getGmtCreate, bloodOutStorageDTO.getEndTime())
                .eq(BloodOutStorgeEntity::getIfShow, IF_SHOW.code())
                .orderByDesc(BloodOutStorgeEntity::getOutStorgeTime);
//
        Map<String, Object> params = new HashMap<>();
        if (Strings.isNotBlank(bloodOutStorageDTO.getLimit())){
            params.put("limit", bloodOutStorageDTO.getLimit());
        }
        if (Strings.isNotBlank(bloodOutStorageDTO.getPage())){
            params.put("page", bloodOutStorageDTO.getPage());
        }
        // 根据进入表格倒序排列
        queryWrapper.orderByDesc(BloodOutStorgeEntity::getGmtCreate);
        IPage<BloodOutStorgeEntity> page = this.page(
                new Query<BloodOutStorgeEntity>().getPage(params),
                queryWrapper
        );

        return new PageUtils(page);
    }
    @Transactional
    @Override
    public boolean bloodOutStorge(Map<String, Object> params) {
//        //生成一个出库表对象
//        BloodOutStorgeEntity bloodOutStorgeEntity = new BloodOutStorgeEntity();
//        if(Strings.isNotBlank((String) params.get("bloodId"))){
//            bloodOutStorgeEntity.setBloodId((String) params.get("bloodId"));//设置血液ID
//        }
//        //获取当前线程认证信息
//        Authentication authentication= SecurityContextHolder.getContext().getAuthentication();
//        if(authentication != null && authentication.isAuthenticated()) {
//            //获取当前用户id、name
//            LoginUser loginUser = (LoginUser) authentication.getPrincipal();
//            //写入当前用户信息
//            bloodOutStorgeEntity.setOperator(loginUser.getUser().getUserName());
//            //设置操作人工号
//            bloodOutStorgeEntity.setOperatorNumber(loginUser.getUser().getUserId());
//            //根据上下文获取工号
//            //生成出库单据号
//            GenerateNumberBySnowFlake outNumber = new GenerateNumberBySnowFlake(bloodOutStorgeEntity.getOperatorNumber(),OUT_STORGE_DOCUMENT_NUMBER.code());
//            //设置出库单据号
//            bloodOutStorgeEntity.setOutStorgeNumber(outNumber.genNumberByflag());
//        }
//        if(Strings.isNotBlank((String) params.get("bloodLocation"))){
//            bloodOutStorgeEntity.setOutStorgeLocation((String) params.get("bloodLocation"));//设置出库地址
//        }
//        bloodOutStorgeEntity.setOutStorgeTime(new Date());//设置出库时间
//        if(Strings.isNotBlank((String) params.get("outStorgeReason"))){
//            bloodOutStorgeEntity.setOutStorgeReason((String) params.get("outStorgeReason"));//设置出库原因
//        }
//        if(Strings.isNotBlank((String) params.get("bloodTaker"))){
//            bloodOutStorgeEntity.setBloodTaker((String) params.get("bloodTaker"));//设置取血人
//        }
//        if(Strings.isNotBlank((String) params.get("bloodTakerNumber"))){
//            bloodOutStorgeEntity.setBloodTakerNumber((String) params.get("bloodTaker"));//设置取血人工号
//        }
//        bloodOutStorgeEntity.setIsDeleted(Integer.valueOf(IS_NOT_TEST_FLAG.code()));
//        int res = bloodOutStorgeDao.insert(bloodOutStorgeEntity);//出库表插入一条数据
//
//        //更新库存血液状态
//        boolean res1 = bloodInformationService.updateBloodStateByBloodId((String) params.get("bloodId"),BLOOD_OUT_STOCK_STATE.code());
//        //更新入库时候的血液状态
//        boolean res2 = bloodInStorgeService.updateInStorgeBloodStatebyBloodId((String) params.get("bloodId"),BLOOD_OUT_STOCK_STATE.code());
//        return res==1 && res1 && res2;
        return true;
    }

    @Override
    public PageUtils queryPageMultipleTable(Map<String, Object> params) {
        //构造bloodoutstorge对象

        QueryWrapper<BloodOutStorgeEntityVo> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq(Strings.isNotBlank((String) params.get("bloodId")),"u.blood_id",(String) params.get("bloodId"));
        queryWrapper.eq(Strings.isNotBlank((String) params.get("bloodBankDeliveryId")), "u.blood_bank_delivery_id", (String) params.get("bloodBankDeliveryId"));
        queryWrapper.eq(Strings.isNotBlank((String) params.get("outStorgeReason")), "u.out_storge_reason", (String) params.get("outStorgeReason"));
        queryWrapper.eq(Strings.isNotBlank((String) params.get("outStorgeLocation")), "u.out_storge_location", (String) params.get("outStorgeLocation"));
        queryWrapper.eq(Strings.isNotBlank((String) params.get("recipientName")), "u.recipient_name", (String) params.get("recipientName"));
        queryWrapper.eq(Strings.isNotBlank((String) params.get("recipientId")), "u.recipient_id", (String) params.get("recipientId"));
        queryWrapper.eq(Strings.isNotBlank((String) params.get("operatorName")), "u.operator_name", (String) params.get("operatorName"));
        queryWrapper.eq(Strings.isNotBlank((String) params.get("operatorId")), "u.operator_id", (String) params.get("operatorId"));
        queryWrapper.eq(Strings.isNotBlank((String)params.get("bloodType")),"o.blood_type",(String)params.get("bloodType"));
        // 时间格式化，解决Date->String 报错
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        String queryTimeStart = (String)params.get("outStorgeTimeStart");
        String queryTimeEnd = (String) params.get("outStorgeTimeEnd");
        Date start = null;
        Date end = null;
        if(Strings.isNotBlank(queryTimeStart) && queryTimeStart != "null"){

            try {
                start = sdf.parse(queryTimeStart);
            }catch (Exception e){
                e.printStackTrace();
            }
        }
        if(Strings.isNotBlank(queryTimeEnd) && queryTimeEnd != "null"){
            try {
                end = sdf.parse(queryTimeEnd);
            }catch (Exception e){
                e.printStackTrace();
            }
        }
        queryWrapper.ge(start != null, "u.out_storge_time", start)
                .le(end != null, "u.out_storge_time", end);
        queryWrapper.eq(Strings.isNotBlank((String) params.get("bloodState")), "o.blood_state", (String) params.get("bloodState"));
        queryWrapper.eq("u.is_deleted",IS_NOT_DELETED.code());
        queryWrapper.eq("u.if_show",IF_SHOW.code());
        queryWrapper.eq("o.if_show",IF_SHOW.code());
        queryWrapper.eq("o.is_deleted",IS_NOT_DELETED.code());
        IPage<BloodOutStorgeEntityVo> page1 = bloodOutStorgeDao.queryPageMultipleTable(new Query<BloodOutStorgeEntityVo>().getPage(params),queryWrapper);
        // 注意：一定要手动关闭 SQL 优化，不然查询总数的时候只会查询主表
        page1.optimizeCountSql();


        return new PageUtils(page1);

    }

    @Override
    @Transactional
    public int urgentOutStorage(BloodUrgentOutStorageVo bloodUrgentOutStorageVo) {
        String bloodId = bloodUrgentOutStorageVo.getBloodId();
        LambdaQueryWrapper<BloodOutStorgeEntity> bloodOutStorageQuery = new LambdaQueryWrapper<>();
        bloodOutStorageQuery.eq(BloodOutStorgeEntity::getBloodId, bloodId);
        BloodOutStorgeEntity bloodOutStorgeEntity = bloodOutStorgeDao.selectOne(bloodOutStorageQuery);
        if (bloodOutStorgeEntity != null){
            throw new MyException(BloodOutStorageException.ALREADY_OUT_STORAGE);
        }

        String operatorName = bloodUrgentOutStorageVo.getOperatorName();
        LambdaQueryWrapper<UserEntity> userEntityQuery = new LambdaQueryWrapper<>();
        userEntityQuery.eq(UserEntity::getUserName,operatorName);
        UserEntity userEntity = userDao.selectOne(userEntityQuery);
        if (userEntity == null){
            throw new MyException(UserLoginException.NO_USER);
        }

        String operatorId = userEntity.getUserId();

        String prefix = ConstantData.BLOOD_OUT_STORAGE_NO_PREFIX;
        String dateStr = new SimpleDateFormat("yyyyMMdd").format(new Date());
        QueryWrapper<BloodOutStorgeEntity> wrapper = new QueryWrapper<>();
        wrapper.likeRight("blood_bank_delivery_id", prefix + dateStr);
        wrapper.orderByDesc("blood_bank_delivery_id");
        wrapper.last("limit 1");
        BloodOutStorgeEntity maxEntity = bloodOutStorgeService.getOne(wrapper);
        int nextSeq = 1;
        if (maxEntity != null && maxEntity.getBloodBankDeliveryId() != null) {
            String maxNo = maxEntity.getBloodBankDeliveryId();
            if (maxNo.length() >= 12) {
                    String seqStr = maxNo.substring(10, 14);
                    nextSeq = Integer.parseInt(seqStr) + 1;
            }
        }

        String seqStr = String.format("%04d", nextSeq);
        String outStorageId = prefix + dateStr +seqStr;
        // 2.更新血液状态为已使用，设置出库单号
        LambdaUpdateWrapper<BloodInformationEntity> bloodInfoUpdateWrapper = new LambdaUpdateWrapper<>();
        bloodInfoUpdateWrapper.set(BloodInformationEntity::getBloodState, BloodStateEnum.USED.code());
        bloodInfoUpdateWrapper.set(BloodInformationEntity::getBloodBankDeliveryId, outStorageId);
        bloodInfoUpdateWrapper.eq(BloodInformationEntity::getBloodId, bloodUrgentOutStorageVo.getBloodId());
        bloodInformationService.update(bloodInfoUpdateWrapper);
        // 3.更新入库表的出库单号
        LambdaUpdateWrapper<BloodInStorgeEntity> inStorgeUpdateWrapper = new LambdaUpdateWrapper<>();
        inStorgeUpdateWrapper.set(BloodInStorgeEntity::getBloodBankDeliveryId, outStorageId);
        inStorgeUpdateWrapper.set(BloodInStorgeEntity::getBloodState, BloodStateEnum.USED.code());
        inStorgeUpdateWrapper.eq(BloodInStorgeEntity::getBloodId, bloodUrgentOutStorageVo.getBloodId());
        bloodInStorgeService.update(inStorgeUpdateWrapper);
        // 4.插入出库表
        BloodOutStorgeEntity outStorgeEntity = new BloodOutStorgeEntity();
        BeanUtils.copyProperties(bloodUrgentOutStorageVo, outStorgeEntity);
        outStorgeEntity.setOutStorgeReason(OutStorageReasonEnum.URGENT.code());
        outStorgeEntity.setBloodBankDeliveryId(outStorageId);
        outStorgeEntity.setOutStorgeTime(new Date());
        outStorgeEntity.setOperatorName(operatorName);
        outStorgeEntity.setOperatorId(operatorId);
        this.save(outStorgeEntity);
        // 5.插入收费表
        BloodChargeEntity bloodChargeEntity = new BloodChargeEntity();
        bloodChargeEntity.setApplyDepartment(bloodUrgentOutStorageVo.getHospitalClassification());
        BeanUtils.copyProperties(bloodUrgentOutStorageVo, bloodChargeEntity);
        String cost = String.valueOf(bloodUrgentOutStorageVo.getBloodPrice());
        bloodChargeEntity.setUnitPrice(cost);
        bloodChargeEntity.setQuantity("1");
        bloodChargeEntity.setTotalPrice(cost);
        bloodChargeEntity.setChargeState(BloodChargeEnum.CHARGE_UNVERIFIED.code());
        bloodChargeEntity.setChargeType(BloodChargeTypeEnum.BLOOD_COST.code());
        bloodChargeEntity.setPayment(PaymentProjectEnum.BLOOD_COST.code());
        bloodChargeService.save(bloodChargeEntity);
        return 0;
    }

    @Override
    public int newSave(BloodOutStorgeEntity bloodOutStorge) {

        String bloodId = bloodOutStorge.getBloodId();
        LambdaQueryWrapper<BloodOutStorgeEntity> bloodOutStorgeQuery = new LambdaQueryWrapper<>();
        bloodOutStorgeQuery.eq(Strings.isNotBlank(bloodId), BloodOutStorgeEntity::getBloodId, bloodId);
        BloodOutStorgeEntity bloodOutStorgeEntity = bloodOutStorgeDao.selectOne(bloodOutStorgeQuery);
        if (bloodOutStorgeEntity != null){
            throw new MyException(BloodOutStorageException.ALREADY_OUT_STORAGE);
        }

        LambdaQueryWrapper<BloodInformationEntity> bloodInformationQuery = new LambdaQueryWrapper<>();
        bloodInformationQuery.eq(Strings.isNotBlank(bloodId), BloodInformationEntity::getBloodId, bloodId);
        BloodInformationEntity bloodInformationEntity = bloodInformationDao.selectOne(bloodInformationQuery);
        if (bloodInformationEntity == null){
            throw new MyException(InstorageException.NO_BLOODID_STORAGE);
        }


        String prefix = ConstantData.BLOOD_OUT_STORAGE_NO_PREFIX;
        String dateStr = new SimpleDateFormat("yyyyMMdd").format(new Date());
        QueryWrapper<BloodOutStorgeEntity> wrapper = new QueryWrapper<>();
        wrapper.likeRight("blood_bank_delivery_id", prefix + dateStr);
        wrapper.orderByDesc("blood_bank_delivery_id");
        wrapper.last("limit 1");
        BloodOutStorgeEntity maxEntity = this.getOne(wrapper);
        int nextSeq = 1;
        if (maxEntity != null && maxEntity.getBloodBankDeliveryId() != null) {
            String maxNo = maxEntity.getBloodBankDeliveryId();
            if (maxNo.length() >= 12) {
                String seqStr = maxNo.substring(10, 14);
                nextSeq = Integer.parseInt(seqStr) + 1;
            }
        }
        String seqStr = String.format("%04d", nextSeq);
        String outStorageId = prefix + dateStr + seqStr;

        // 2.更新血液信息表状态为已使用，设置出库单号
        LambdaUpdateWrapper<BloodInformationEntity> bloodInfoUpdateWrapper = new LambdaUpdateWrapper<>();
        bloodInfoUpdateWrapper.set(BloodInformationEntity::getBloodState, BloodStateEnum.USED.code());
        bloodInfoUpdateWrapper.set(BloodInformationEntity::getBloodBankDeliveryId, outStorageId);
        bloodInfoUpdateWrapper.eq(BloodInformationEntity::getBloodId, bloodOutStorge.getBloodId());
        bloodInformationService.update(bloodInfoUpdateWrapper);

        // 3.更新入库表的出库单号
        LambdaUpdateWrapper<BloodInStorgeEntity> inStorgeUpdateWrapper = new LambdaUpdateWrapper<>();
        inStorgeUpdateWrapper.set(BloodInStorgeEntity::getBloodState, BloodStateEnum.USED.code());
        inStorgeUpdateWrapper.set(BloodInStorgeEntity::getBloodBankDeliveryId, outStorageId);
        inStorgeUpdateWrapper.eq(BloodInStorgeEntity::getBloodId, bloodOutStorge.getBloodId());
        bloodInStorgeService.update(inStorgeUpdateWrapper);

        // 4.插入出库表
        bloodOutStorge.setOutStorgeReason(bloodOutStorge.getOutStorgeReason());
        bloodOutStorge.setBloodBankDeliveryId(outStorageId);
        bloodOutStorge.setOutStorgeTime(new Date());
        this.save(bloodOutStorge);

        // 5.插入收费表

//        BloodInformationEntity bloodInfo = bloodInformationService.getById(bloodOutStorge.getBloodId());
       BloodChargeEntity bloodChargeEntity = new BloodChargeEntity();

            bloodChargeEntity.setApplyDepartment(bloodInformationEntity.getHospitalClassification());
            BeanUtils.copyProperties(bloodInformationEntity, bloodChargeEntity);
            String cost = String.valueOf(bloodInformationEntity.getBloodPrice());
            bloodChargeEntity.setUnitPrice(cost);
            bloodChargeEntity.setQuantity("1");
            bloodChargeEntity.setTotalPrice(cost);

        bloodChargeEntity.setChargeState(BloodChargeEnum.CHARGE_UNVERIFIED.code());
        bloodChargeEntity.setChargeType(BloodChargeTypeEnum.BLOOD_COST.code());
        bloodChargeEntity.setPayment(PaymentProjectEnum.BLOOD_COST.code());
        bloodChargeService.save(bloodChargeEntity);

        return 0;

    }
}
